package cn.cagurzhan.service;

import cn.cagurzhan.common.exception.IotException;
import cn.cagurzhan.common.properties.IotProperties;
import cn.cagurzhan.domain.dto.CommandResultDto;
import cn.cagurzhan.domain.dto.DeviceShadowDto;
import cn.cagurzhan.domain.entity.EnvLog;
import cn.cagurzhan.utils.StringUtils;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.huaweicloud.sdk.cce.v3.model.Runtime;
import com.huaweicloud.sdk.core.auth.AbstractCredentials;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.*;
import com.huaweicloud.sdk.iotda.v5.region.IoTDARegion;
import com.huaweicloud.sdk.vpc.v3.VpcClient;
import com.huaweicloud.sdk.vpc.v3.model.ListVpcsRequest;
import com.huaweicloud.sdk.vpc.v3.model.ListVpcsResponse;
import com.huaweicloud.sdk.vpc.v3.region.VpcRegion;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 封装华为云IoT SDK
 * @author AjaxZhan
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class IoTService {


    private final IotProperties iotProperties;

    private static IoTDAClient client = null;

    /**
     * 创建基础连接
     * @return 连接客户端
     */
    public IoTDAClient initClient(){
        // 节约请求认证次数
        if(client!=null){
            return client;
        }
        // 通过SK和AK认证
        ICredential auth = new BasicCredentials()
                .withDerivedPredicate(AbstractCredentials.DEFAULT_DERIVED_PREDICATE) // Used in derivative ak/sk authentication scenarios
                .withAk(iotProperties.getAk())
                .withSk(iotProperties.getSk());
        // 创建客户端
        client = IoTDAClient.newBuilder()
                .withCredential(auth)
                .withRegion(IoTDARegion.valueOf(iotProperties.getRegion()))
                .build();
        return client;
    }

    /**
     * 拿到设备影子中的参数
     * @param client 通过init拿到的客户端
     * @param deviceId 设备ID
     * @return 设备参数
     */
    public Map<String,Object> getDeviceShadowProperties(IoTDAClient client, String deviceId){
        if(StringUtils.isEmpty(deviceId) || ObjectUtil.isNull(client)){
            throw new IotException("getDeviceShadow异常：设备ID或client为空");
        }
        // 封装request
        ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
        request.setDeviceId(deviceId);
        // 发送请求
        try {
            ShowDeviceShadowResponse response = client.showDeviceShadow(request);
            String jsonString = JSON.toJSONString(response);
            DeviceShadowDto deviceShadowDto = JSON.parseObject(jsonString, DeviceShadowDto.class);
            return (Map<String,Object> ) deviceShadowDto.getShadow().get(0).getReported().get("properties");
        } catch (ConnectionException | RequestTimeoutException e) {
            log.warn("getDeviceShadow异常：{}",e.getMessage());
        } catch (ServiceResponseException e) {
            log.warn("getDeviceShadow异常：{}，状态码：{}，请求ID：{}，错误码：{}，错误信息：{}"
                    ,e.getMessage(),e.getHttpStatusCode(),e.getRequestId(),e.getErrorCode(),
                            e.getErrorMsg());
        }
        return null;
    }

    /**
     * 下发命令
     * @param client 客户端
     * @param deviceId 设备ID
     * @param serviceId 服务ID
     * @param commandName 命令名称
     * @param params 参数
     * @return 命令返回参数，需要使用者判断是否为错误消息
     */
    public CommandResultDto sendCommand(IoTDAClient client, String deviceId,String serviceId,String commandName, Map<String,Object> params){
        if(StringUtils.isEmpty(deviceId) || ObjectUtil.isNull(client)){
            throw new IotException("sendCommand异常：设备ID或client为空");
        }
        if(StringUtils.isEmpty(commandName) || ObjectUtil.isNull(params)){
            throw new IotException("sendCommand异常：命令或者参数为空");
        }

        // 构造请求
        CreateCommandRequest request = new CreateCommandRequest();
        request.setDeviceId(deviceId);
        // 构造请求体
        DeviceCommandRequest body = new DeviceCommandRequest();
        body.withCommandName(commandName);
        String paras = JSON.toJSONString(params);
        body.withParas(paras);
        body.withServiceId(serviceId);
        request.withBody(body);

        // 发送请求
        try {
            CreateCommandResponse response = client.createCommand(request);
            String jsonString = JSON.toJSONString(response);
            log.error(jsonString);
            return JSON.parseObject(jsonString, CommandResultDto.class);
        } catch (ConnectionException | RequestTimeoutException e) {
            log.warn("sendCommand异常：{}",e.getMessage());
        } catch (ServiceResponseException e) {
            log.warn("sendCommand异常：{}，状态码：{}，请求ID：{}，错误码：{}，错误信息：{}"
                    ,e.getMessage(),e.getHttpStatusCode(),e.getRequestId(),e.getErrorCode(),
                    e.getErrorMsg());
        }
        return null;
    }

    /**
     * 创建规则：属性上报时触发
     */
    public void onPropertiesUpload(IoTDAClient client){

        CreateRoutingRuleRequest request = new CreateRoutingRuleRequest();
        AddRuleReq body = new AddRuleReq();
        RoutingRuleSubject subjectbody = new RoutingRuleSubject();
        subjectbody.withResource("device.property")
                .withEvent("report");
        body.withAppType("GLOBAL");
        body.withSubject(subjectbody);
        body.withDescription("description");
        body.withRuleName("finger_who_test");
        request.withBody(body);
        try {
            CreateRoutingRuleResponse response = client.createRoutingRule(request);
            System.out.println(JSON.toJSONString(response));
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
            System.out.println(e.getHttpStatusCode());
            System.out.println(e.getRequestId());
            System.out.println(e.getErrorCode());
            System.out.println(e.getErrorMsg());
        }
    }

    // public void test2(){
    //     CreateRuleActionRequest request = new CreateRuleActionRequest();
    //     AddActionReq body = new AddActionReq();
    //     HttpForwarding httpForwardingChannelDetail = new HttpForwarding();
    //     httpForwardingChannelDetail.withUrl("http://host:port/callbackurltest");
    //     ChannelDetail channelDetailbody = new ChannelDetail();
    //     channelDetailbody.withHttpForwarding(httpForwardingChannelDetail);
    //     body.withChannelDetail(channelDetailbody);
    //     body.withChannel("HTTP_FORWARDING");
    //     body.withRuleId("1a7ffc5c-d89c-44dd-8265-b1653d951ce0");
    //     request.withBody(body);
    //     try {
    //         CreateRuleActionResponse response = client.createRuleAction(request);
    //         System.out.println(response.toString());
    //     } catch (ConnectionException e) {
    //         e.printStackTrace();
    //     } catch (RequestTimeoutException e) {
    //         e.printStackTrace();
    //     } catch (ServiceResponseException e) {
    //         e.printStackTrace();
    //         System.out.println(e.getHttpStatusCode());
    //         System.out.println(e.getRequestId());
    //         System.out.println(e.getErrorCode());
    //         System.out.println(e.getErrorMsg());
    //     }
    // }

}
